/**************************************************************************************
*  TermThread.java
**************************************************************************************
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL RTJ COMPUTING BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Copyright (c) 2000-2002 RTJ Computing Pty. Ltd. All rights reserved.
**************************************************************************************/
import java.util.*;
import lpc2xxx.hw.*;
import lpc2xxx.comm.*;


class TermThread extends Thread
{
    private UART port;
    boolean terminated = false;

    TermThread(UART port)
    {
        this.port = port;
    }

    void showExcep(Exception exc)
    {
        Console.println("UART exception. " + exc.getMessage());
    }

    public void terminate()
    {
        terminated = true;
    }

    public void run()
    {
        try
        {
            port.write("\r\nTerminal thread started.\r\n");
            displayMenu();
        }
        catch (Exception exc)
        {
            showExcep(exc);
        }
        boolean presentChoice = true;
        while (!terminated)
        {
            try
            {
                if (presentChoice)
                {
                    port.write("\r\nYour choice (0 for menu): ");
                    presentChoice = false;
                }
                if (!port.isDataAvail()) 
                {
                    yield();
                    continue;
                }

                byte choice = port.read();
                if (choice == 0x1B)
                    terminated = true;
                else if (choice == 0x0D)
                    presentChoice = true;
                else if (choice >= '0' && choice <= '5')
                {
                    presentChoice = true;
                    port.write(choice);
                    port.write("\r\n");
                    switch (choice)
                    {
                        case '0':
                            displayMenu();
                            break;
                        case '1':
                            invertChars();
                            break;
                        case '2':
                            duplicateChars();
                            break;
                        case '3':
                            port.write("Total VM heap: "+System.totalMemory()+"\r\n");
                            break;
                        case '4':
                            port.write("Free VM heap: "+System.freeMemory()+"\r\n");
                            break;
                        case '5':
                            int before = System.freeMemory();
                            int start = System.currentTimeMillis();
                            System.gc();
                            int end = System.currentTimeMillis();
                            int after = System.freeMemory();
                            port.write("GC completed in " + (end - start) + " ms\r\n");
                            port.write("Free memory before: " + before + " bytes\r\n");
                            port.write("Free memory after:  " + after + " bytes\r\n");
                            break;
                    }
                }
            }
            catch (Exception exc)
            {
                showExcep(exc);
                break;
            }
        }
        Console.println("Thread exit");
    }

    void displayMenu() throws Exception
    {
        port.write("  0   - display this menu\r\n");
        port.write("  1   - invert case of incomming characters\r\n");
        port.write("  2   - duplicate incomming characters\r\n");
        port.write("  3   - display total size of VM heap\r\n");
        port.write("  4   - display free size of VM heap\r\n");
        port.write("  5   - run Garbage Collector\r\n");
        port.write("  ESC - exit\r\n");
    }

    void invertChars() throws Exception
    {
        while (true)
        {
            while (!port.isDataAvail())
               yield();

           byte ch = port.read();
           if (ch == 0x1B)
               break;

           if (ch >= 'A' && ch <= 'Z')
               port.write((byte)(ch + 0x20));
           else if (ch >= 'a' && ch <= 'z')
               port.write((byte)(ch - 0x20));
            else
               port.write(ch);
        }
    }

    void duplicateChars() throws Exception
    {
        while (true)
        {
            while (!port.isDataAvail())
               yield();

           byte ch = port.read();
           if (ch == 0x1B)
               break;

           port.write(ch);
           port.write(ch);
        }
    }
}
